/**
 * @Copyright 2017 Sinosoft Co. Ltd. All rights reserved.<br/>
 * 项目名称 : 交银康联智能运营平台
 * 创建日期 : 2017年5月24日
 * 修改历史 : 
 *     1. [2017年5月24日]创建文件 by sinosoft
 */
package com.darth.aop.aspect;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.darth.aop.dto.LkclienttranlogWithBLOBs;
import com.darth.aop.service.ClientLogService;
import com.darth.common.enums.ENUM_RESULT;
import com.darth.common.exception.CommonRuntimeException;
import com.darth.common.exception.dto.common.Head;
import com.darth.common.utils.DateUtil;

/**
 *
 * 【facade接口报文请求拦截器】
 *
 * @author sinosoft
 * @date 2017年8月8日
 * @version V1.0
 */
@Aspect
@Component
public class WebFacadeInsureAspect {

    private static final Logger log = LoggerFactory.getLogger(WebFacadeInsureAspect.class);

    @Autowired
    private ClientLogService clientLogService;
    
    //正则表达式配置切入包，类，方法
    @Pointcut("execution(public * com.sinosoft.common.epay.controller.UnionPayController.*(..))")
    public void WebFacadeAspectAop() {}

    @Around(value = "WebFacadeAspectAop()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String logPrefix = "[WebFacadeInsureAspect.doAround].[";
        long startTime = System.currentTimeMillis();//开始时间
        long endTime = 0;//结束时间
        LkclienttranlogWithBLOBs lkTranLog = new LkclienttranlogWithBLOBs();//日志记录
        try {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest(); // 获取request信息

            String method = request.getMethod();
            String uri = request.getRequestURI(); // 获取请求地址
            int n = uri.lastIndexOf("/");
            String interfaceCode = uri.substring(n + 1);
            //			String queryString = request.getQueryString();
            //			Map<?, ?> inputParamMap = request.getParameterMap();
            String params = "";
            if ("POST".equals(method)) {
                Object[] paramsArray = proceedingJoinPoint.getArgs();
                params = argsArrayToString(paramsArray);
            }
            //1、记录开始log日志
            log.info("{}开始时间 {},请求接口：{},请求报文：{}]",logPrefix,DateUtil.getDateStr(new Date(startTime)),interfaceCode,params);
            JSONObject json = JSON.parseObject(params);
            Head head = JSON.parseObject(json.get("transactionInfo").toString(), Head.class);

          //2、重复校验
            Boolean exist = clientLogService.queryLog(head.getTransactionid(), head.getSourcecode());
            if (exist != null && exist.booleanValue()) {
                throw new CommonRuntimeException("重复请求");
            }
            
            String prtno = getRequestprtno(params);//获取订单号，如果报文中没有订单号，返回空
            //3、封装数据库日志-开始信息
            lkTranLog.setTranno(head.getTransactionid());// 交易流水号
            lkTranLog.setSourcecode(head.getSourcecode());// 商户编码
            lkTranLog.setOrderno(prtno);// 投保单号
            lkTranLog.setBusinesstype("Dar.th"); // 业务类型
            lkTranLog.setCategory(interfaceCode);// 接口区分
            lkTranLog.setRequesttime(new Date(startTime));// 请求时间
            lkTranLog.setRequestcontent(json.toString());// 请求内容
            lkTranLog.setMakedate(DateUtil.getCurrentDate());// 入机时间

            //4、调用拦截方法
            //result的值就是被拦截方法的返回值
            Object result = proceedingJoinPoint.proceed();
            endTime = System.currentTimeMillis();//结束时间
            float useTime = ((endTime - startTime) / 1000.0f);//用时

            //5、封装数据库日志-结束信息，并落入数据库
            lkTranLog.setResponsecontent(result.toString());//返回报文
            lkTranLog.setResponsetime(new Date(endTime));//返回时间
            lkTranLog.setUsedtime(useTime);// 耗时
            lkTranLog.setState(getResultStatus(result.toString())); // 交易状态
            try {
                clientLogService.addTranLog(lkTranLog);
            }catch (Exception e) {
                log.error("{}日志记录数据库出现异常，原因：", logPrefix, e);
            }

            //6、记录结束log日志
            log.info("{}结束时间：{},用时:{},请求接口：{}]",logPrefix, DateUtil.getDateStr(new Date(endTime)),useTime,interfaceCode);
            log.info("{}返回报文：{}]" ,logPrefix, result );
            return result;
        }catch (CommonRuntimeException e) {
            String failReturn = createErrorRepeat(ENUM_RESULT.FAIL, e.getMessage());
            log.error("{}请求失败，原因：{}]" ,logPrefix, e.getMessage());
            log.error("{}返回报文：{}]",logPrefix, failReturn );
            return failReturn;
        }catch (Exception e) {
            String errorReturn = createErrorRepeat(ENUM_RESULT.UNUSUAL, e.getMessage());
            log.error("{}出现系统异常，原因：" ,logPrefix, e);
            log.error("{}返回报文：{}]",logPrefix, errorReturn );
            return errorReturn;
        }
    }

    /**
     * 请求参数拼装
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
                Object jsonObj = JSON.toJSON(paramsArray[i]);
                params += jsonObj.toString() + " ";
            }
        }
        return params.trim();
    }

    /*
     * 从返回信息中获取返回code
     */
    private String getRequestprtno(String requestJson) {
        int n = requestJson.indexOf("orderno");
        if (n == -1) {
            return "";
        }

        String temp = requestJson.substring(n);
        String orderno = temp.split(",")[0];
        orderno = orderno.replace("orderno", "").replace("\"", "").replace(",", "").replace(":", "").replaceAll("\\s+", "");
        return orderno;
    }

    /*
     * 从返回信息中获取返回code
     */
    private String getResultStatus(String result) {
        JSONObject resultJson = JSON.parseObject(result);
        JSONObject statusJson = resultJson.getJSONObject("response").getJSONObject("status");
        return statusJson.getString("statuscode");
    }

    /*
     * 创建返回报文
     */
    private String createErrorRepeat(ENUM_RESULT rtnType, String errorMsg) {
        String errorRepeat = "{\"response\":{\"status\":{\"statuscode\":\"" + rtnType.code() + "\",\"statusmessage\":[\"交易异常\",\"" + errorMsg + "\"]}}}";
        return errorRepeat;
    }

}
